package com.youhome.service.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.youhome.common.exception.CustomException;
import com.youhome.common.queue.CompanyReportQueueList;
import com.youhome.common.response.ResultCode;
import com.youhome.service.dto.DTOCompanyReport;
import com.youhome.service.dto.DTOHousePropertyType;
import com.youhome.service.mapper.CompanyReportMapper;
import com.youhome.service.model.CompanyReport;
import com.youhome.service.model.CustomCompanyTokenDetails;
import com.youhome.service.model.ListHub;
import com.youhome.service.service.CompanyReportService;
import com.youhome.service.service.ListHubService;
import com.youhome.service.service.UploadService;
import com.youhome.utils.ModelMapperUtils;
import org.modelmapper.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by chen365 on 2019/05/23.
 */
@Service
public class CompanyReportServiceImpl implements CompanyReportService {
    @Autowired
    private CompanyReportMapper companyReportMapper;
    @Autowired
    private ListHubService listHubService;
    @Autowired
    private UploadService uploadService;

    @Override
    public PageInfo<DTOCompanyReport> selectByBean(Integer pageIndex, Integer pageSize, CompanyReport record) {
        if (pageIndex == null || pageIndex < 1) {
            pageIndex = 1;
        }

        if (pageSize == null || pageSize < 1) {
            pageSize = 10;
        }

        PageHelper.startPage(pageIndex, pageSize);
        List<CompanyReport> companyReports = companyReportMapper.selectByBean(record);
        return new PageInfo<>(ModelMapperUtils.toList(companyReports, new TypeToken<List<DTOCompanyReport>>() {
        }.getType()));
    }

    @Override
    public CompanyReport selectByPrimaryKey(Long reportId) throws CustomException {
        CompanyReport companyReport = companyReportMapper.selectByPrimaryKey(reportId);
        if (companyReport == null) {
            throw new CustomException(ResultCode.NOT_EXIST_REPORT);
        }
        return companyReport;
    }

    @Override
    public CompanyReport generate(CustomCompanyTokenDetails companyTokenDetails, Integer reportType, String houseId) throws CustomException {

        Long companyId = companyTokenDetails.getCompanyId();
        Long companyTokenId = companyTokenDetails.getTokenId();

        ListHub listHub = listHubService.selectDetailsByHouseId(houseId);
        if (listHub == null) {
            throw new CustomException(ResultCode.HOUSE_INEXISTENCE);
        }
        CompanyReport companyReport = new CompanyReport();

        companyReport.setCompanyId(companyId);
        companyReport.setCompanyTokenId(companyTokenId);
        companyReport.setHouseId(listHub.getHouseId());
        companyReport.setReportType(reportType);

        if (companyReportMapper.selectIsExistByBean(companyReport) > 0) {
            throw new CustomException(ResultCode.REPORT_HAS_GENERATED);
        }

        String reportPath = UUID.randomUUID().toString().replaceAll("-", "") + ".pdf";

        companyReport.setHouseAddress(listHub.getAddress());
        companyReport.setHouseZipcode(listHub.getZip());
        companyReport.setReportPath(reportPath);
        companyReport.setReportStatus(0);
        companyReport.setDownloadCount(0);
        companyReport.setCreated(new Date());
        companyReport.setUpdated(new Date());

        int row = companyReportMapper.insertSelective(companyReport);

        System.err.println("row:" + row);
        System.err.println("companyReport:" + companyReport.toString());

        CompanyReportQueueList.push(companyReport);
        create();
        return companyReport;
    }

    @Override
    public CompanyReport selectByPrimaryKey(Long reportId, CustomCompanyTokenDetails companyTokenDetails) throws CustomException {
        CompanyReport companyReport = companyReportMapper.selectByPrimaryKey(reportId);
        if (companyReport == null) {
            throw new CustomException(ResultCode.NOT_EXIST_REPORT);
        }
        if (!companyReport.getCompanyId().equals(companyTokenDetails.getCompanyId())) {
            throw new CustomException(ResultCode.ILLEGAL_OPERATION);
        }
        return companyReport;
    }

    public void create() throws CustomException {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        scheduledThreadPool.scheduleAtFixedRate(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行。。。");
            do {
                //获取队列对像
                Object obj = CompanyReportQueueList.get();
                CompanyReport report = (CompanyReport) obj;
                //生成PDF
                createPDF(report);
            } while (CompanyReportQueueList.isEmpty());
        }, 1, 3, TimeUnit.SECONDS);
    }

    public void createPDF(CompanyReport report) {
        System.err.println("开始生成报告。。。");
        Boolean success = false;
        long start = System.currentTimeMillis();
        String sourceUrl = "";
        String targetPDF = "";
        String command = "";

        if (report.getReportType() == 0) {
            sourceUrl = "report/free/" + report.getHouseId();
        } else {
            sourceUrl = "report/charge/" + report.getHouseId();
        }

        String os = System.getProperty("os.name");

        if (os.toLowerCase().startsWith("win")) {
            sourceUrl = "http://localhost:8086/" + sourceUrl;
            targetPDF = "c:/out/report/" + report.getReportPath();
            command = "phantomjs C:/Java/tool/rasterize.js " + sourceUrl + " " + targetPDF;
        } else if (os.toLowerCase().startsWith("mac")) {
            sourceUrl = "http://localhost:9090/" + sourceUrl;
            targetPDF = "/data/report/" + report.getReportPath();
            command = "phantomjs /usr/local/phantomjs/examples/rasterize.js " + sourceUrl + " " + targetPDF;
        } else {
            sourceUrl = "http://localhost:8091/" + sourceUrl;
            targetPDF = "/data/report/" + report.getReportPath();
            command = "phantomjs /data/report/rasterize.js " + sourceUrl + " " + targetPDF;
        }

        System.err.println("command:" + command);
        try {
            Process p = Runtime.getRuntime().exec(command);
            InputStream is = p.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuffer stringBuffer = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                stringBuffer.append(line);
            }
            p.waitFor();
            is.close();
            reader.close();
            p.destroy();
            System.err.println("stringBuffer.toString()==>>" + stringBuffer.toString());
            if (StringUtils.isEmpty(stringBuffer.toString())) {
                success = true;
                System.err.println("已生成报告。。。");
            } else {
                System.err.println("生成报告失败。。。");
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println((System.currentTimeMillis() - start) + " 毫秒");

        int status = 2;  //失败
        if (success) {
            //上传oss
            if (uploadService.uploadReport(targetPDF)) {
                status = 1;
            } else {
                status = 2;
            }
        }

        CompanyReport record = new CompanyReport();

        record.setReportId(report.getReportId());
        record.setReportStatus(status);
        record.setUpdated(new Date());

        companyReportMapper.updateByPrimaryKeySelective(record);
    }
}
